﻿$.BEdit = $({
	__init : function (sets) {
		this.sets = $.extend({
			line_tag : 'tr',
			item_tag : 'td',
			action_btn_class : 'action-btn',
			origin_value_class : 'origin-value',
			value_cnt_class : 'value-cnt',
			record_id_rel : 'rid',
			update_text : '更新',
			insert_text :  '添加',
			delete_text : '删除',
			edit_text : '编辑',
			cancel_text : '取消',
			action_btn_tpl : '<a href="javascript:void(0)" class="action-btn" baction="{0}">${{0}_text}</a>',
			useForm : false
		}, sets || {});
		if (!this.sets.cnt) throw "no cnt";
		this.clickHandle = this.__click.bindAsEventListener(this);
		$.observe(this.sets.cnt[0], 'click', this.clickHandle);
		this.action_url = this.sets.action_url || location.toString();
		this.checkers = $.clone($.BEdit.DCheckers, this.sets.checkers);
		if (this.sets.useForm) {
			this.f = $($('<form action="{0}" method="post"><input type="hidden" name="baction"/></form>'.format(this.action_url)));
			this.f.addTo(document.body);
		} else {
			this.ajaxSuccessHandle = this.sets.onSuccess || $.empty;
			this.ajaxErrorHandle = this.sets.onError || $.empty;
		}
	},
	__click : function (event) {
		var e = $(event, 'element');
		var le = $(event, 'find', this.sets.line_tag);
		if ($(e).$('$$class', this.sets.action_btn_class)) {
			this.__action_btn(e, le);	
		}
		$(event, 'stop');
	},
	__action_btn : function (btn, line_e) {
		btn = $(btn);
		var ac_name = btn.$('baction');
		if (ac_name) {
			if (this['__do_' + ac_name]) return this['__do_' + ac_name](line_e, btn);
			if (this.f) {
				this.__form_post(ac_name, line_e);
			} else {
				this.__ajax_post(ac_name, line_e);				
			}
		}
	},
	__do_edit : function (line_e, $btn) {
		var _t = this;
		$(this.sets.item_tag + '[@bfield]', line_e).each(function(item){
			item = $(item);
			var field_name = item.$('bfield');
			var value_cnt = item.find('*.' + _t.sets.value_cnt_class);
			if (value_cnt.length == 0) throw "no value_cnt";
			var origin_value_cnt = item.find('*.' + _t.sets.origin_value_class);
			if (origin_value_cnt.length == 0) throw "no origin_value_cnt";
			var origin_value = origin_value_cnt.html();
			if(_t.sets.select_fields && _t.sets.select_fields[field_name]) {
				var ops = _t.sets.select_fields[field_name], htmls = [];
				htmls.push('<select name="{0}">'.format(field_name));
				for (var i = 0; i < ops.length; i++) {
					htmls.push('<option value="{0}" {1}>{2}</option>'.format(ops[i].value, ops[i].value == origin_value ? "selected=\"selected\"" : "", ops[i].text));
				}	
				htmls.push('</select>');
				value_cnt.html(htmls.join(''));
			} else {
				var input = $('<input type="text" value="" name="' + field_name + '"/>');
				input.value = origin_value;
				value_cnt.empty().append(input);
			}
		});
		//change btn 
		var btn_group_html = ['<span class="action-btn-group">', 
							_t.sets.action_btn_tpl.format('update').process(_t.sets),
							'<span class="bspace">&nbsp;|&nbsp;</span>',
							_t.sets.action_btn_tpl.format('cancel').process(_t.sets),
						'</span>'].join('').process(_t.sets);
		$btn.before($(btn_group_html)).remove();
	},
	__do_cancel : function (line_e, $btn) {
		this.bind_origin_values(line_e, $btn);
	},
	bind_origin_values : function (line_e, $btn) {
		var _t = this;
		$(this.sets.item_tag + '[@bfield]', line_e).each(function(item){
			item = $(item);
			var field_name = item.$('bfield');
			var origin_value = item.find('*.' + _t.sets.origin_value_class).html();
			if (_t.sets.processors && _t.sets.processors[field_name]) {
				origin_value = _t.sets.processors[field_name](origin_value);
			}
			item.find('*.' + _t.sets.value_cnt_class).html(origin_value);
		});
		var btn_group = $('*.action-btn-group', line_e);
		if (btn_group.length != 0) {
			var edit_btn = $(_t.sets.action_btn_tpl.format('edit').process(_t.sets));
			btn_group.before(edit_btn).remove();
		}
	},
	__do_new : function () {
		if (this.sets.line_tpl) return;
		//var item = $(this.sets	
	},
	__update_succ : function (line_e) {
		var _t = this;
		$(this.sets.item_tag + '[@bfield]', line_e).each(function(item){
			item = $(item);
			var field_name = item.$('bfield');
			var inputOrSel = item.find('*.' + _t.sets.value_cnt_class + ' input');
			if (inputOrSel.length == 0) inputOrSel = item.find('*.' + _t.sets.value_cnt_class + ' select');
			if (inputOrSel.length == 0) return;
			var new_value = inputOrSel.$('value');
			 item.find('*.' + _t.sets.origin_value_class).html(new_value)
			if (_t.sets.processors && _t.sets.processors[field_name]) {
				new_value = _t.sets.processors[field_name](new_value);
			}
			item.find('*.' + _t.sets.value_cnt_class).html(new_value);
		});
		var btn_group = $('*.action-btn-group', line_e);
		var edit_btn = $(_t.sets.action_btn_tpl.format('edit').process(_t.sets));
		btn_group.before(edit_btn).remove();
	},
	__delete_succ : function (line_e) {
		line_e.parentNode.removeChild(line_e);	
	},
	__insert_succ : function (line_e, json) {
		json = json || {};
		if (this.sets.insert_inplace) {
			if (json.id) $(line_e).$(this.sets.record_id_rel, json.id);
			__update_succ(line_e);
		} else {
			if (this.sets.create_line) {
				var line_e = this.sets.create_line(json);
				this.sets.cnt[0].appendChild(line_e);
				this.bind_origin_values(line_e);
			}
		}
	},
	__ajax_post : function (ac_name, line_e) {
		var params = this.__get_params(line_e);
		//参数不合法
		if (params === null) return;
		params['baction'] = ac_name;
		(this.sets.onPosting || $.empty)();
		var _t = this;
		new $.Ajax.Simple(this.action_url, {
			method: 'post', 
			postBody : this.__to_query_str(params),
			onSuccess: function(t){
				var json = $.jeval(t.responseText);
				if (_t['__' + ac_name + '_succ']) _t['__' + ac_name + '_succ'](line_e, json);
				_t.ajaxSuccessHandle(json, ac_name);
			},
			onFailure: this.ajaxErrorHandle});
	},
	__form_post : function (ac_name, line_e) {
		var params = this.__get_params(line_e);
		//参数不合法
		if (params === null) return;
		this.f.find('input[name=baction]')[0].value = ac_name;
		for (var name in params) {
			if ($.isString(params[name])) {
				var input = this.f.find('input[name={0}]'.format(name));
				if (!input || input.length == 0) {
					this.f.append($('<input type="hidden" name="{0}" value=""/>'));	
					input = this.f.find('input[name={0}]'.format(name));
				}
				input[0].value = params[name];
			}
		}
		this.f[0].submit();
	},
	__get_params : function (line_e) {
		var ret = {}, e = $(line_e);
		e.$(this.sets.record_id_rel) && (ret['id'] = e.$(this.sets.record_id_rel));
		var value_valid = true, _t = this;
		e.find('input[type=text]').each(function(input){
			if (input.name) {
				var v = input.value, n = input.name;
				if (_t.sets.rules && _t.sets.rules[n]) {
					var rules = [].concat(_t.sets.rules[n]);
					for (var i = 0; i < rules.length; i++) {
						var rule = rules[i];	
						if (_t.checkers[rule.type] && !_t.checkers[rule.type](v.trim(), rule.param)) {
							(_t.sets['error_' + n] || _t.sets['error_all'] || $.empty)(v, n, rule.msg);
							value_valid = false;
							throw $break;		
						}
					}
				}
				ret[n] = v;	
			}
		});
		if (!value_valid) return null;
		e.find('select').each(function(sel){
			sel.name && (ret[sel.name] = $(sel).$('value'));	
		});
		return ret;
	},
	__to_query_str : function (p) {
		var a = [];
		for (var pro in p) {
			if (!$.isFunction(p[pro])) {
				a.push(pro + '=' + ('' + p[pro]).encode());	
			}	
		}
		return a.join('&');	
	},
	
	destroy: function () {
		$.stopObserving(this.stes.cnt, 'click', this.clickHandle);
		this.clickHandle = null;
		this.sets = null;
		if (this.f) {
			this.f = null;	
		} else {
			this.ajaxSuccessHandle = 	this.ajaxErrorHandle = null;
		}
	}
});
$.BEdit.DCheckers = {
	notEmpty : function (v) { return v && !v.isEmpty() },
	digit : function (v, range) {
		if (!v || !/^\d+$/.test(v))	return false;
		if (!range) return true;
		var v = parseInt(v, 10);
		return v >= range[0] && v <= range[1];
	},
	lengthLimit : function (v, max) {
		return (v || '').length <= max;	
	},
	mlengthLimit : function (v, max) {
		return (v || '').replace(/[^\x00-\xff]/g, 'aa').length <= max;	
	}
};
$.BEdit.DCheckers.required = $.BEdit.DCheckers.notEmpty;